#include<iostream>
#include<string.h>

using namespace std;

//深浅拷贝——利用模拟实现basic_string深入理解
namespace yfy
{
	class string
	{
	public:
		string(const char* str)
			:_str(new char[strlen(str)+1])	//若此处不在堆上开空间，而是将str作为参数赋值给_str，就是浅拷贝，其后果是无法修改常量字符串
		{
			strcpy(_str, str);
		}

		string(const string& s)
			:_str(new char[strlen(s._str) + 1])		//自定义拷贝构造函数，深拷贝————开辟同样大小空间，并将数据拷贝
		{
			strcpy(_str, s._str);
		}

		~string()
		{
			delete[] _str;
			_str = nullptr;
		}

		char& operator[](size_t pos)
		{
			return _str[pos];
		}

		string& operator=(const string& s)			//不管左值右值谁长，直接将左值释放，开辟和右值同样大小空间，再拷贝右值
		{
			if (this != &s)		//防止自己给自己赋值
			{
				char* tmp = new char[strlen(s._str) + 1];	//如果先释放_str，new失败了会导致赔了夫人又折兵，new如果失败会抛异常，所以先不要释放_str，new成功后再释放
				delete[] _str;									
				_str = tmp;
				strcpy(_str, s._str);
			}
			return *this;
		}
	private:
		char* _str;
	};

	void test_string1()
	{
		string s1("hello");
		s1[0] = 'x';
		string s2(s1);//若是编译器默认实现的拷贝构造，则为浅拷贝————导致：1、同一块空间析构两次 2、一个对象修改值，另一个随之改变
		string s3("hello world");
		s1 = s3;
	}
}

int main()
{
	yfy::test_string1();
	return 0;
}
